package main

import (
	"fmt"
	"sync"
	"time"
)

// Queue 表示一个线程安全的队列结构。
type Queue struct {
	queue []string
	cond  *sync.Cond
}

func main() {
	// 初始化一个 Queue 实例，并设置条件变量。
	q := Queue{
		queue: make([]string, 0),
		cond:  sync.NewCond(&sync.Mutex{}),
	}
	// 启动一个 goroutine，周期性地向队列中添加数据。
	go func() {
		for {
			q.Enqueue("a")
			time.Sleep(time.Second * 2)
		}
	}()
	// 主程序，周期性地从队列中取出数据。
	for {
		q.Dequeue()
		time.Sleep(time.Second)
	}
}

// Enqueue 向队列中添加一个元素。
// 参数 item: 要添加到队列中的字符串元素。
func (q *Queue) Enqueue(item string) {
	q.cond.L.Lock()
	defer q.cond.L.Unlock()
	q.queue = append(q.queue, item)
	fmt.Println("将 %s 放入队列，通知所有等待者\n", item)
	// 通知所有等待者，队列中已经有新的数据。
	q.cond.Broadcast()
	// 通知单个等待者，队列中已经有新的数据。
	//q.cond.Signal()
}

// Dequeue 从队列中取出一个元素并返回。
// 如果队列为空，则等待直到有数据可用。
// 返回值: 从队列中取出的字符串元素。
func (q *Queue) Dequeue() string {
	q.cond.L.Lock()
	defer q.cond.L.Unlock()
	for len(q.queue) == 0 {
		fmt.Println("没有可用数据，等待")
		q.cond.Wait()
	}
	// 取出第一个结果，并将其从队列中移除。
	result := q.queue[0]
	q.queue = q.queue[1:]
	return result
}
